/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package groupchat;

import java.util.Iterator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import org.restlet.Application;
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.Restlet;
import org.restlet.data.Method;
import org.restlet.data.Reference;
import org.restlet.data.Status;
import org.xeerkat.agent.AgentContext;
import org.xeerkat.agent.GroupChat;
import org.xeerkat.agent.Task;
import org.xeerkat.agent.services.ServiceMetadata;
import org.xeerkat.xmpp.ID;

/**
 *
 * @author alex
 */
@ServiceMetadata(id="http://www.xeerkat.org/Service/Test/OwnerChat/1/0",vendor="xeerkat.org",copyright="2010 xeerkat.org")
public class OwnerChatApplication extends Application {

   static CountDownLatch CREATED = new CountDownLatch(1);
   static CountDownLatch LATCH = new CountDownLatch(1);
   static AtomicBoolean SUCCESS = new AtomicBoolean(true);
   
   AgentContext agentContext;
   String role;
   boolean converse;
   ID chatId;
   GroupChat chat;
   public OwnerChatApplication(Context context) {
      super(context);
   }

   public Restlet createInboundRoot() {
      return new Restlet(getContext()) {
         public void handle(Request request, Response response) {
            getLogger().info(agentContext.getIdentity()+" MESSAGE: "+request.getEntityAsText());
            response.setStatus(Status.SUCCESS_NO_CONTENT);
         }
      };
   }

   public void start() 
      throws Exception
   {
      boolean started = isStarted();
      super.start();
      if (started) {
         return;
      }
      if (LATCH.getCount()==0) {
         return;
      }

      agentContext = (AgentContext)getContext().getAttributes().get(AgentContext.AGENT_CONTEXT_ATTR);
      role = getContext().getParameters().getFirstValue("role");
      chatId = new ID(getContext().getParameters().getFirstValue("conference")+"/"+agentContext.getIdentity().getName());
      converse = "true".equals(getContext().getParameters().getFirstValue("converse"));

      getLogger().info(agentContext.getIdentity()+" is "+role+" for "+chatId+" (conversing="+converse+")");

      Task test = agentContext.getTaskManager().create(new Runnable() {
         public void run() {
            if (role.equals("owner")) {
               getLogger().info(agentContext.getIdentity()+" is creating chat "+chatId);
               try {
                  chat = agentContext.joinChat(chatId, getContext().getParameters().getFirstValue("password"), new GroupChat.Listener() {

                     public void onCreateFailed(int code, String reason) {
                        getLogger().severe(agentContext.getIdentity()+" Error ("+code+"): "+reason);
                        SUCCESS.set(false);
                        LATCH.countDown();
                     }

                     public void onJoinFailed(int code, String reason) {
                        getLogger().severe(agentContext.getIdentity()+" Cannot join room ("+code+"): "+reason);
                        SUCCESS.set(false);
                        LATCH.countDown();
                     }

                     public void onReady() {
                        getLogger().info(agentContext.getIdentity()+" Room created, role="+chat.getRole()+", affiliation="+chat.getAffiliation());
                        if (converse) {
                           CREATED.countDown();
                           Task conversation = agentContext.getTaskManager().create(new Runnable() {
                              public void run() {
                                 try {
                                    Thread.sleep(1000);
                                    Iterator<ID> members = chat.getMembers();
                                    while (members.hasNext()) {
                                       getLogger().info(agentContext.getIdentity()+" member: "+members.next());
                                    }
                                    if (!message("hello")) {
                                       finish();
                                       return;
                                    }
                                    if (!message("how+are+you?")) {
                                       finish();
                                       return;
                                    }
                                    if (!message("goodbye!")) {
                                       finish();
                                       return;
                                    }
                                    ParticipantChatApplication.CONVERSATION.await(5000, TimeUnit.SECONDS);
                                    Thread.sleep(2000);
                                    finish();
                                 } catch (Exception ex) {
                                    ex.printStackTrace();
                                 }
                              }
                              void finish() {
                                 chat.leave();
                                 LATCH.countDown();
                              }
                           });
                           agentContext.getTaskManager().run(conversation);
                        } else {
                           chat.leave();
                           LATCH.countDown();
                        }
                     }

                     public void onJoin(ID id) {
                        getLogger().info(agentContext.getIdentity()+ " joined: "+id);
                     }

                     public void onLeave(ID id) {
                        getLogger().info(agentContext.getIdentity()+" Left: "+id);
                     }

                     public void onDecline(ID id, String reason) {
                        getLogger().info(agentContext.getIdentity()+" Declined: "+id+", "+reason);
                     }

                  });
               } catch (Exception ex) {
                  getLogger().log(Level.SEVERE,"Cannot join chat.",ex);
                  SUCCESS.set(false);
               }
            }
         }
      });
      agentContext.getTaskManager().run(test);
   }

   boolean message(String text) {
      Request message = agentContext.createRequest(Method.POST,new Reference("xmpp:"+chat.getRoom()+"?message;type=groupchat&body="+text));
      Response response = getContext().getClientDispatcher().handle(message);
      if (!response.getStatus().isSuccess()) {
         getLogger().severe("XMPP request failed ("+response.getStatus().getCode()+") "+response.getEntityAsText());
         SUCCESS.set(false);
         return false;
      }
      return true;
   }

}
